/*
 * Created by Jaren at 2023/9/25 11:06
 */
import 'dart:typed_data';

import 'package:inmotion_protocol/base/base_factory.dart';
import 'package:inmotion_protocol/common/exceptions.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/elephant/constant.dart';
import 'package:inmotion_protocol/elephant/message.dart';
import 'package:inmotion_protocol/elephant/util.dart';
import 'package:inmotion_protocol/elephant/cryptor.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

class ElephantMessageFactory extends MsgFactory<ElephantMessage> {
  @override
  void init(ProductProperty productProperty) {
    model = productProperty.model;
    version = productProperty.versionWrapper;
  }

  static ElephantMessage genRequestInitInfoMsg() {
    /// 读取64个长度，从主控板 至 产品型号
    return genReadMsg(ElephantConstant.extraFuncInitInfo, intData: 32 * 2);
  }

  static ElephantMessage genRequestBtVersionMsg() {
    return genReadMsg(ElephantConstant.extraFuncBtVersion, intData: 2);
  }

  static ElephantMessage genRequestAllRealTimeInfoMsg() {
    // 工作模式0x2D - 姿态温度0x4C
    // 共 29*2 bytes
    // return genReadMsg(ElephantConstant.extraFuncRealTimeInfo, intData: 29 * 2);

    // 错误代码0x29 - 当前车速0x34
    // 共 12*2 bytes
    return genReadMsg(ElephantConstant.extraFuncErrorCode, intData: 12 * 2);
  }

  static ElephantMessage genRequestRealTimeInfoMsg() {
    // 电量 至 车速，共10个字节
    return genReadMsg(ElephantConstant.extraFuncBatteryLevel, intData: 10);
  }

  static ElephantMessage genRequestDynamicSpeedLimitMsg() {
    return genReadMsg(ElephantConstant.extraFuncDynamicSpeedLimit, intData: 2);
  }

  static ElephantMessage genRequestHeadlightStateMsg() {
    return genReadMsg(ElephantConstant.extraFuncLightState, intData: 1);
  }

  /// 生成获取错误代码消息
  static ElephantMessage genRequestErrorCodeMsg() {
    return genReadMsg(ElephantConstant.extraFuncErrorCode, intData: 4);
  }

  static ElephantMessage genRequestWorkModeMsg() {
    return genReadMsg(ElephantConstant.extraFuncRealTimeInfo, intData: 2);
  }

  static ElephantMessage genPowerOffMsg() {
    return genWriteMsg(ElephantConstant.extraFuncPowerOff, ByteUtil.num2BytesLe(1, 1));
  }

  static ElephantMessage genRequestStatisticsInfoMsg() {
    return genReadMsg(ElephantConstant.extraFuncTotalRideMileage, intData: 20 * 2);
  }

  static ElephantMessage genMsg(int device, int function, int extra, Uint8ClampedList data) {
    // function + extra + data
    int length = (1 + 1 + data.length);

    int encrypt = Cryptor.randomIndex();
    // length + encrypt + device + function + extra + data
    Uint8ClampedList bytesNeedCheck = Uint8ClampedList(1 + 1 + 1 + 1 + 1 + data.length);
    bytesNeedCheck[0] = length;
    bytesNeedCheck[1] = encrypt;
    bytesNeedCheck[2] = device;
    bytesNeedCheck[3] = function;
    bytesNeedCheck[4] = extra;
    ByteUtil.copy(data, 0, bytesNeedCheck, 5, data.length);
    ElephantMessage msg = ElephantMessage();

    msg.length = ByteUtil.toUint8(length);
    msg.encrypt = ByteUtil.toUint8(encrypt);
    msg.device = ByteUtil.toUint8(device);
    msg.function = ByteUtil.toUint8(function);
    msg.extra = ByteUtil.toUint8(extra);
    msg.data = data;
    msg.check = ElephantUtil.calSumCheck(bytesNeedCheck);
    return msg;
  }

  /// 生成 获取数据 消息
  /// 通讯设备 - 主控板
  /// - [extra] int
  /// - [data] bytes 附带数据段内容。与[intData]二选一
  /// - [intData] int 读取数据长度，1byte，与[data]二选一
  static ElephantMessage genReadMsg(int extra, {Uint8ClampedList? data, int? intData}) {
    if (data == null && intData == null) throw InvalidParamException("Param [data] and [intData] cannot be both empty.");
    return genMsg(ElephantConstant.commDeviceController, ElephantConstant.funcReadInfo, extra, data ?? ByteUtil.num2BytesLe(intData!, 1));
  }

  /// 生成 写入数据 消息
  /// 通讯设备 - 主控板
  static ElephantMessage genWriteMsg(int extra, Uint8ClampedList data) {
    return genMsg(ElephantConstant.commDeviceController, ElephantConstant.funcWriteInfo, extra, data);
  }

  /// 生成 获取数据 消息
  /// 通讯设备 - 蓝牙板
  static ElephantMessage genReadBtMsg(int extra, Uint8ClampedList data) {
    return genMsg(ElephantConstant.commDeviceBt, ElephantConstant.funcReadInfo, extra, data);
  }

  /// 生成 写入数据 消息
  /// 通讯设备 - 蓝牙板
  static ElephantMessage genWriteBtMsg(int extra, Uint8ClampedList data) {
    return genMsg(ElephantConstant.commDeviceBt, ElephantConstant.funcReadInfo, extra, data);
  }

  /// 读取log（黑匣子）
  static ElephantMessage genReadLogMsg(int start) {
    // data[0]和扩展功能码合并使用，得到读取地址address = Data[0]<<8 | extra;
    // data[1]要读取的长度，必须是8。
    Uint8ClampedList addressBytes = ByteUtil.num2BytesLe(start, 2);
    return genMsg(ElephantConstant.commDeviceController, ElephantConstant.funcLog, addressBytes[0], Uint8ClampedList.fromList([addressBytes[1], 8]));
  }
}
